package pub.developers.forum.app.manager;


import org.springframework.core.Conventions;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import pub.developers.forum.api.model.PageRequestModel;
import pub.developers.forum.api.model.PageResponseModel;
import pub.developers.forum.api.request.comment.CommentCreateRequest;
import pub.developers.forum.api.response.comment.CommentPageResponse;
import pub.developers.forum.app.support.IsLogin;
import pub.developers.forum.app.support.LoginUserContext;
import pub.developers.forum.app.transfer.CommentTransfer;
import pub.developers.forum.common.enums.*;
import pub.developers.forum.common.model.PageResult;
import pub.developers.forum.common.support.CheckUtil;
import pub.developers.forum.common.support.EventBus;
import pub.developers.forum.domain.entity.BasePosts;
import pub.developers.forum.domain.entity.Comment;
import pub.developers.forum.domain.entity.Message;
import pub.developers.forum.domain.entity.User;
import pub.developers.forum.domain.entity.value.IdValue;
import pub.developers.forum.domain.repository.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


@Component
public class CommentManager {

    @Resource
    private CommentRepository commentRepository;

    @Resource
    private PostsRepository postsRepository;

    @Resource
    private UserRepository userRepository;


    @Resource
    private ApprovalRepository approvalRepository;

    @Resource
    private MessageRepository messageRepository;



    @IsLogin
    @Transactional(rollbackFor = Exception.class)
    public void create(CommentCreateRequest request) throws Exception {
        BasePosts posts = postsRepository.get(request.getPostsId());
        CheckUtil.isEmpty(posts, ErrorCodeEn.POSTS_NOT_EXIST);

        Comment comment = CommentTransfer.toComment(request, LoginUserContext.getUser());

        if (!ObjectUtils.isEmpty(comment.getReplyId())) {
            Comment reply = commentRepository.get(comment.getReplyId());
            CheckUtil.isEmpty(reply, ErrorCodeEn.COMMENT_NOT_EXIST);
            CheckUtil.isFalse(reply.getPostsId().equals(request.getPostsId()), ErrorCodeEn.COMMENT_POSTS_NOT_EXIST);

            if (!ObjectUtils.isEmpty(reply.getReplyId())) {
                comment.setReplyReplyId(reply.getId());
                comment.setReplyId(reply.getReplyId());
            }
        }

        // 保存
        commentRepository.save(comment);

        // 增加帖子评论数
        postsRepository.increaseComments(posts.getId(), posts.getUpdateAt());

        Map<String, Object> msg = new HashMap<>();
        msg.put("commenter", LoginUserContext.getUser().getId());
        msg.put("comment", comment);
        EventBus.emit(EventBus.Topic.COMMENT_CREATE, msg);
    }
    public List<CommentPageResponse> getListByPostId(Long postId) {

        // 查询一级评论
        List<Comment> commentList = commentRepository.queryByPostsId(postId);

        if (ObjectUtils.isEmpty(commentList)) {
            return new ArrayList<>();
        }
        List<Comment> firstList = commentList.stream().filter(c-> c.getReplyId() == null && c.getReplyReplyId() == null).collect(Collectors.toList());
        List<CommentPageResponse> responseList = getCommentList(firstList, null, commentList);
        return responseList;
    }

    private List<CommentPageResponse> getCommentList(List<Comment> commentList, User commentUser, List<Comment> allList){
        if (commentList == null || commentList.size() == 0){
            return null;
        }
        List<Long> userIdList = commentList.stream().map(Comment::getUserId).collect(Collectors.toList());
        List<User> users = userRepository.queryByIds(userIdList);
        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity()));
        List<CommentPageResponse> responseList = new ArrayList<>();
        for (Comment comment : commentList){
            CommentPageResponse commentPageResponse = new CommentPageResponse();
            commentPageResponse.setContent(comment.getContent());
            commentPageResponse.setId(comment.getId());
            commentPageResponse.setReplyId(comment.getReplyId());
            commentPageResponse.setCreateAt(comment.getCreateAt());
            commentPageResponse.setFollowCount(comment.getFollowCount());

            User user = userMap.get(comment.getUserId());
            if (user != null){
                CommentPageResponse.Commentator commentator = new CommentPageResponse.Commentator();
                commentator.setId(user.getId());
                commentator.setAvatar(user.getAvatar());
                commentator.setNickname(user.getNickname());
                commentPageResponse.setCommentator(commentator);
            }
            if (commentUser != null){
                CommentPageResponse.Commentator commentator = new CommentPageResponse.Commentator();
                commentator.setId(commentUser.getId());
                commentator.setAvatar(commentUser.getAvatar());
                commentator.setNickname(commentUser.getNickname());
                commentPageResponse.setRespondent(commentator);
            }
            List<Comment> filterList = allList.stream().filter(c-> c.getReplyId() == comment.getId()).collect(Collectors.toList());
            commentPageResponse.setReplies(getCommentList(filterList, user, allList));
            responseList.add(commentPageResponse);
        }
        return responseList;
    }

    @IsLogin
    public PageResponseModel<CommentPageResponse> page(PageRequestModel<Long> pageRequest) {

        // 获取当前登录用户的id
        Long id = LoginUserContext.getUser().getId();

        // 查询一级评论
        PageResult<Comment> pageResult = commentRepository.page(pageRequest.getPageNo(), pageRequest.getPageSize(), pageRequest.getFilter());

        if (ObjectUtils.isEmpty(pageResult.getList())) {
            return PageResponseModel.build(pageResult.getTotal(), pageResult.getSize(), new ArrayList<>());
        }

        List<User> users = userRepository.queryByIds(pageResult.getList().stream()
                .map(Comment::getUserId)
                .collect(Collectors.toList()));

        List<CommentPageResponse> responses = CommentTransfer.toCommentPageResponses(pageResult.getList(), users, false);

        // 用于存储一级评论id和对应的二级评论个数
        Map<Long, Long> replyCountMap = new HashMap<>();

        for (CommentPageResponse commentPageResponse : responses) {
            // 判断当前用户是否给这个评论点赞了
            commentPageResponse.setIsLike(approvalRepository.isLike(id, commentPageResponse.getId()));

            // 查询一级评论对应的二级评论个数
            List<Comment> replies = commentRepository.queryInReplyIdsCount(Collections.singleton(commentPageResponse.getId()));
            replyCountMap.put(commentPageResponse.getId(), (long) replies.size());
        }

        // 设置每个一级评论的二级评论个数
        responses.forEach(commentPageResponse -> commentPageResponse.setRelpiesCount(replyCountMap.getOrDefault(commentPageResponse.getId(), 0L)));

        //前三条二级评论
        pageResult.getList().stream().map(Comment::getId).collect(Collectors.toList()); //拿到一级评论的id
        List<Comment> replies = commentRepository.queryThreeInReplyIds(pageResult.getList().stream()
                .map(Comment::getId)
                .collect(Collectors.toSet()));
        if (ObjectUtils.isEmpty(replies)) {
            return PageResponseModel.build(pageResult.getTotal(), pageResult.getSize(), responses);
        }


        for(Comment comment : replies)
        {
            //判断当前用户是否给这个评论点赞了
            comment.setIsLike(approvalRepository.isLike(id, comment.getId()));
        }

        List<User> replyUsers = userRepository.queryByIds(replies.stream()
                .map(Comment::getUserId)
                .collect(Collectors.toList()));


        List<CommentPageResponse> replyComments = CommentTransfer.toCommentPageResponses(replies, replyUsers, true);
        responses.forEach(response -> {
            response.setReplies(replyComments.stream().filter(replyComment ->
                    replyComment.getReplyId().equals(response.getId()))
                    .collect(Collectors.toList()));
        });


        return PageResponseModel.build(pageResult.getTotal(), pageResult.getSize(), responses);
    }


    //根据一级评论的id 拿到二级评论
    @IsLogin
    public PageResponseModel<CommentPageResponse> replyPage(PageRequestModel pageRequestModel)
    {
        //拿到当前登录用户的id
        Long id = LoginUserContext.getUser().getId();
        List<CommentPageResponse> replyComments = new ArrayList<>();

        PageResult<Comment> replies = commentRepository.queryInReplyIds(Collections.singleton(Long.valueOf((Integer) pageRequestModel.getFilter()))
                , pageRequestModel.getPageSize(), pageRequestModel.getPageNo());

        if (!ObjectUtils.isEmpty(replies.getList()))
        {
            for(Comment comment : replies.getList())
            {
                //判断当前用户是否给这个评论点赞了
                comment.setIsLike(approvalRepository.isLike(id, comment.getId()));
            }
            List<User> replyUsers = userRepository.queryByIds(replies.getList().stream()
                .map(Comment::getUserId)
                .collect(Collectors.toList()));
            replyComments = CommentTransfer.toCommentPageResponses(replies.getList(), replyUsers, true);
        }
        return PageResponseModel.build(replies.getTotal(), replies.getSize() , replyComments);
    }


    // 收到的评论消息
    @IsLogin
    public List<CommentPageResponse> beCommented(){

        User user = LoginUserContext.getUser();

        List<Comment> comments = commentRepository.queryInReplyIdOrReplyReplyId(user.getId());
        List<CommentPageResponse> res = new ArrayList<>();

        for (Comment comment : comments) {
            CommentPageResponse commentPageResponse = new CommentPageResponse();
            user = userRepository.get(comment.getUserId());
            // 用户信息
            CommentPageResponse.Commentator commentator = new CommentPageResponse.Commentator();
            commentator.setId(user.getId());
            commentator.setNickname(user.getNickname());
            commentator.setAvatar(user.getAvatar());
            commentPageResponse.setCommentator(commentator);

            commentPageResponse.setContent(comment.getContent());
            commentPageResponse.setCreateAt(comment.getCreateAt());
            commentPageResponse.setId(comment.getId());
            commentPageResponse.setReplyId(comment.getReplyId());
            res.add(commentPageResponse);
        }
        return res;
    }

    //给评论点赞功能
    @IsLogin
    public void followCommentManager(Long commentID)
    {
        //拿到用户登录id
        Long userId = LoginUserContext.getUser().getId();
        commentRepository.followCommentRepository(userId , commentID);
        //根据评论id 拿到发这条评论的人的id
        Comment comment = commentRepository.get(commentID);
        //接收者的id 应该是发送这条评论的人的id
        Message message = Message.builder()
                .channel(MessageChannelEn.STATION_LETTER)
                .receiver(IdValue.builder()
                        .id(String.valueOf(comment.getUserId()))
                        .type(IdValueTypeEn.USER_ID)
                        .build())
                .read(MessageReadEn.NO)
                .contentType(MessageContentTypeEn.TEXT)
                .content("")
                .sender(IdValue.builder()
                        .id(userId.toString())
                        .type(IdValueTypeEn.USER_ID)
                        .build())
                .build();
        // 判断是否存在
        Message tmp =messageRepository.getBySenderAndReceiver(userId.toString(),commentID.toString(),"MessageTypeEn.COMMENT_FOLLOW");
        CheckUtil.isNotEmpty(tmp, ErrorCodeEn.REPEAT_OPERATION);
        message.setType(MessageTypeEn.COMMENT_FOLLOW);
        messageRepository.updateToRead(message);
    }

    //给评论取消点赞的功能
    @IsLogin
    public void unfollowCommentManager(Long commentID)
    {
        //拿到当前登录用户的id
        Long userId = LoginUserContext.getUser().getId();
        commentRepository.unfollowCommentRepository(userId , commentID);
    }

}
